"""Smart import service with AI multi-intention parsing."""

from __future__ import annotations

import json
import re
from typing import Any

from pydantic import BaseModel, Field

from ..models.enums import DemandType, IntentionLevel
from ..schemas.lead import LeadCreate
from ..schemas.lead_intention import LeadIntentionCreate
from ..services.unified_ai_service import get_ai_service


class ParsedIntention(BaseModel):
    """单个意向解析结果."""

    demand_type: DemandType
    budget_min: int | None = None
    budget_max: int | None = None
    area_preferences: str | None = None  # JSON 字符串
    layout: str | None = None
    requirement_tags: str | None = None  # JSON 字符串
    priority: int = 1
    intention_level: IntentionLevel = IntentionLevel.MEDIUM
    notes: str | None = None


class ConfidenceBreakdown(BaseModel):
    """置信度详细分析."""

    # 总分
    total_score: float = Field(..., description="总分（0-100）")
    final_confidence: float = Field(..., description="最终置信度（0-1）")

    # 各维度得分
    required_fields_score: float = Field(..., description="必填字段完整性（0-40）")
    optional_fields_score: float = Field(..., description="可选字段完整性（0-30）")
    validation_score: float = Field(..., description="数据合理性验证（0-20）")
    ai_confidence_score: float = Field(..., description="AI自评置信度（0-10）")

    # 详细评分项
    scores: dict[str, Any] = Field(default_factory=dict, description="详细评分项")


class ParsedLeadWithIntentions(BaseModel):
    """客户解析结果（含主意向和额外意向）."""

    # 客户主信息
    lead: LeadCreate

    # 额外意向（可选，可为空列表）
    additional_intentions: list[ParsedIntention] = Field(default_factory=list)

    # AI 置信度
    confidence: float = Field(0.0, ge=0.0, le=1.0)

    # 置信度详细分析（可选）
    confidence_breakdown: ConfidenceBreakdown | None = None


class BatchParseResult(BaseModel):
    """批量解析结果."""

    items: list[ParsedLeadWithIntentions]
    total: int
    success: int
    failed: int


class SmartImportService:
    """智能导入服务（支持多意向解析）."""

    MAX_TEXT_LENGTH = 1000  # 单条文本最大长度
    BATCH_SIZE = 5  # 单批最大数量

    def __init__(self):
        """初始化智能导入服务 (使用统一AI服务)"""
        self.ai_service = get_ai_service()

    def _detect_scenario_complexity(self, text: str) -> str:
        """
        检测场景复杂度

        Args:
            text: 客户信息文本

        Returns:
            "simple" 或 "complex"

        规则:
        - 检测是否包含多个客户标识 (客户1、客户2、姓名1、姓名2等)
        - 检测文本长度 (>500字视为复杂)
        - 检测意向数量关键词
        """
        # 检测多客户标识
        multi_customer_patterns = [
            r"客户[1-9]",  # 客户1, 客户2
            r"第[一二三四五]个客户",
            r"(?:姓名|名字)[1-9]",
        ]

        for pattern in multi_customer_patterns:
            if re.search(pattern, text):
                return "complex"

        # 长文本视为复杂场景
        if len(text) > 500:
            return "complex"

        # 默认简单场景
        return "simple"

    async def parse_single_lead(self, text: str, scenario: str | None = None) -> ParsedLeadWithIntentions:
        """
        解析单个客户信息（支持多意向）.

        Args:
            text: 客户信息文本（限制1000字符）
            scenario: 强制指定场景 ("simple"/"complex"), 如果为None则自动检测

        Returns:
            解析结果（主意向 + 额外意向）
        """
        # 字数限制
        if len(text) > self.MAX_TEXT_LENGTH:
            text = text[: self.MAX_TEXT_LENGTH]

        # 自动检测场景复杂度
        if scenario is None:
            scenario = self._detect_scenario_complexity(text)

        # 构建 AI Prompt
        prompt = self._build_parse_prompt(text)

        # 调用统一AI服务 (传递场景参数)
        try:
            response = await self.ai_service.call_llm(
                prompt,
                temperature=0.1,
                max_tokens=1500,
                scenario=scenario  # type: ignore
            )

            # 清理AI响应：去除markdown代码块标记
            cleaned_response = response.strip()
            if cleaned_response.startswith("```json"):
                cleaned_response = cleaned_response[7:]  # 去除 ```json
            if cleaned_response.startswith("```"):
                cleaned_response = cleaned_response[3:]  # 去除 ```
            if cleaned_response.endswith("```"):
                cleaned_response = cleaned_response[:-3]  # 去除结尾 ```
            cleaned_response = cleaned_response.strip()

            # 解析JSON，处理可能的多余内容（如GLM返回多个JSON对象）
            try:
                parsed_data = json.loads(cleaned_response)
            except json.JSONDecodeError:
                # 如果失败，尝试只解析第一个JSON对象
                decoder = json.JSONDecoder()
                try:
                    parsed_data, idx = decoder.raw_decode(cleaned_response)
                    if idx < len(cleaned_response):
                        # 有额外内容，记录警告但继续使用第一个有效JSON
                        print(f"Warning: Extra content found after JSON (length: {len(cleaned_response) - idx})")
                except json.JSONDecodeError:
                    # 完全无法解析，抛出原始错误
                    raise

            # 解析主意向（Lead）
            lead_data = parsed_data.get("lead", {})
            lead = LeadCreate(
                name=lead_data.get("name", ""),
                phone=lead_data.get("phone", ""),
                demand_type=DemandType(lead_data.get("demand_type", "rent_whole")),
                budget_range=lead_data.get("budget_range"),
                source_channel=lead_data.get("source_channel", "wechat"),
                stage=lead_data.get("stage", "new"),
                notes=text,  # 保存原始文本
                tag_names=lead_data.get("tag_names"),
                owner_id=1,  # 临时设置，实际导入时会被替换
                import_batch_id="00000000-0000-0000-0000-000000000000",  # 临时设置
            )

            # 解析额外意向
            additional_intentions = []
            raw_intentions = parsed_data.get("additional_intentions", [])
            for idx, intention_data in enumerate(raw_intentions):
                intention = ParsedIntention(
                    demand_type=DemandType(intention_data.get("demand_type", "rent_whole")),
                    budget_min=intention_data.get("budget_min"),
                    budget_max=intention_data.get("budget_max"),
                    area_preferences=json.dumps(intention_data.get("area_preferences", []))
                    if intention_data.get("area_preferences")
                    else None,
                    layout=intention_data.get("layout"),
                    requirement_tags=json.dumps(intention_data.get("requirement_tags", []))
                    if intention_data.get("requirement_tags")
                    else None,
                    priority=idx + 1,  # 按顺序设置优先级
                    intention_level=IntentionLevel(
                        intention_data.get("intention_level", "medium")
                    ),
                    notes=intention_data.get("notes"),
                )
                additional_intentions.append(intention)

            # 计算置信度（基于实际验证）
            confidence, breakdown = self._calculate_confidence(lead, parsed_data)

            return ParsedLeadWithIntentions(
                lead=lead,
                additional_intentions=additional_intentions,
                confidence=confidence,
                confidence_breakdown=breakdown,
            )

        except Exception as e:
            print(f"AI 解析失败: {e}")
            # 返回空结果
            return ParsedLeadWithIntentions(
                lead=LeadCreate(
                    name="",
                    phone="",
                    demand_type=DemandType.RENT_WHOLE,
                    owner_id=1,
                    import_batch_id="00000000-0000-0000-0000-000000000000",
                ),
                additional_intentions=[],
                confidence=0.0,
            )

    async def parse_batch(self, texts: list[str]) -> BatchParseResult:
        """
        批量解析客户信息（自动分批，每批5条）.

        Args:
            texts: 客户信息文本列表

        Returns:
            批量解析结果
        """
        total = len(texts)
        batches = [texts[i : i + self.BATCH_SIZE] for i in range(0, total, self.BATCH_SIZE)]

        all_results = []
        success_count = 0
        failed_count = 0

        for batch_idx, batch in enumerate(batches):
            print(f"Processing batch {batch_idx + 1}/{len(batches)}...")

            for text in batch:
                try:
                    result = await self.parse_single_lead(text)
                    all_results.append(result)

                    if result.confidence > 0.7:
                        success_count += 1
                    else:
                        failed_count += 1
                except Exception as e:
                    print(f"解析失败: {e}")
                    failed_count += 1

        return BatchParseResult(
            items=all_results, total=total, success=success_count, failed=failed_count
        )

    def _build_parse_prompt(self, text: str) -> str:
        """
        构建解析 Prompt.

        Args:
            text: 客户信息文本

        Returns:
            Prompt 字符串
        """
        return f"""你是房产CRM数据处理专家。请从以下文本中提取客户信息和意向。

文本（限1000字符）：
{text}

【重要】提取规则：
1. lead 字段：客户主信息和第一个意向（主意向）
2. additional_intentions 字段：额外的意向（可选，可为空数组）
3. 如果只有1个意向，additional_intentions 为空数组
4. 如果有多个意向，第一个作为主意向，其余放入 additional_intentions
5. **如果文本中包含多个客户（如"客户1"、"客户2"），只提取第一个客户的信息**
6. **必须只返回一个JSON对象，绝对不要返回多个JSON对象**

返回JSON格式（严禁使用markdown代码块，直接返回纯JSON）：
{{
  "lead": {{
    "name": "客户姓名",
    "phone": "手机号（11位）",
    "demand_type": "rent_whole",  // rent_whole/rent_shared/rent_short/buy/sell
    "budget_range": "7000-8000",  // 第一个意向的预算
    "source_channel": "wechat",   // wechat/phone/referral/other
    "stage": "new",
    "tag_names": "近地铁,安静"     // 逗号分隔的主需求标签
  }},
  "additional_intentions": [
    {{
      "demand_type": "rent_shared",
      "budget_min": 3000,
      "budget_max": 4000,
      "area_preferences": ["CBD", "国贸"],
      "layout": "1室",
      "requirement_tags": ["安静", "近地铁"],
      "intention_level": "medium",  // high/medium/low/none
      "notes": "备选方案"
    }}
  ],
  "_confidence": 0.95  // AI自评置信度(0-1)
}}

注意：
- area_preferences 和 requirement_tags 使用数组格式
- 如果只有1个意向，additional_intentions 为空数组
- 预算单位自动识别（元/月 或 万元）
"""

    def _extract_budget_range(self, budget_min: int | None, budget_max: int | None) -> str | None:
        """从 budget_min/max 生成 budget_range 字符串."""
        if budget_min and budget_max:
            return f"{budget_min}-{budget_max}"
        elif budget_min:
            return f"{budget_min}+"
        elif budget_max:
            return f"<{budget_max}"
        return None

    def _calculate_confidence(
        self, lead: LeadCreate, parsed_data: dict[str, Any]
    ) -> tuple[float, ConfidenceBreakdown]:
        """
        计算置信度（基于实际验证的严谨算法）.

        评分维度（总分100分）：
        1. 必填字段完整性 (40分)
           - 姓名：10分
           - 手机号格式：20分
           - 需求类型：10分

        2. 可选字段完整性 (30分)
           - 预算范围：10分
           - 来源渠道：5分
           - 标签：15分

        3. 数据合理性验证 (20分)
           - 手机号规则：10分（11位，1开头）
           - 预算合理性：10分（租房<50000，买房>100000等）

        4. AI自评置信度 (10分)
           - AI返回的_confidence * 10

        Args:
            lead: 解析后的客户数据
            parsed_data: AI返回的原始JSON数据

        Returns:
            (置信度分数, 详细分析数据)
        """
        # 详细评分项
        scores: dict[str, Any] = {}

        # 各维度得分
        required_score = 0.0
        optional_score = 0.0
        validation_score = 0.0
        ai_score = 0.0

        # 1. 必填字段完整性 (40分)
        # 姓名 (10分)
        name_score = 0.0
        if lead.name and len(lead.name.strip()) >= 2:
            name_score = 10
        elif lead.name and len(lead.name.strip()) >= 1:
            name_score = 5  # 单字姓名只给5分
        required_score += name_score
        scores['name'] = {'score': name_score, 'max': 10, 'value': lead.name or ''}

        # 手机号格式 (20分)
        phone = lead.phone or ""
        phone_format_score = 0.0
        if self._validate_phone(phone):
            phone_format_score = 20
        elif len(phone) >= 11:
            phone_format_score = 10  # 长度够但格式不对，给一半分
        required_score += phone_format_score
        scores['phone_format'] = {'score': phone_format_score, 'max': 20, 'value': phone}

        # 需求类型 (10分)
        demand_type_score = 10 if lead.demand_type else 0
        required_score += demand_type_score
        scores['demand_type'] = {
            'score': demand_type_score,
            'max': 10,
            'value': lead.demand_type.value if lead.demand_type else ''
        }

        # 2. 可选字段完整性 (30分)
        # 预算范围 (10分)
        budget_score = 10 if (lead.budget_range and len(lead.budget_range) > 0) else 0
        optional_score += budget_score
        scores['budget_range'] = {'score': budget_score, 'max': 10, 'value': lead.budget_range or ''}

        # 来源渠道 (5分)
        channel_score = 5 if (lead.source_channel and lead.source_channel != "other") else 0
        optional_score += channel_score
        scores['source_channel'] = {'score': channel_score, 'max': 5, 'value': lead.source_channel or ''}

        # 标签 (15分)
        tags_score = 15 if (lead.tag_names and len(lead.tag_names) > 0) else 0
        optional_score += tags_score
        scores['tags'] = {'score': tags_score, 'max': 15, 'value': lead.tag_names or ''}

        # 3. 数据合理性验证 (20分)
        # 手机号规则验证 (10分)
        phone_strict_score = 0.0
        if self._validate_phone_strict(phone):
            phone_strict_score = 10
        elif phone and phone[0] == '1' and len(phone) == 11:
            phone_strict_score = 5  # 格式基本对，给一半分
        validation_score += phone_strict_score
        scores['phone_validation'] = {
            'score': phone_strict_score,
            'max': 10,
            'message': '符合中国手机号规则' if phone_strict_score == 10 else
                      ('格式基本正确' if phone_strict_score == 5 else '格式错误')
        }

        # 预算合理性 (10分)
        budget_valid = self._validate_budget_reasonability(lead.demand_type, lead.budget_range)
        budget_validation_score = 10 if budget_valid else 0
        validation_score += budget_validation_score
        scores['budget_validation'] = {
            'score': budget_validation_score,
            'max': 10,
            'message': '预算范围合理' if budget_valid else '预算范围不合理或缺失'
        }

        # 4. AI自评置信度 (10分)
        ai_confidence = parsed_data.get("_confidence", 0.5)
        ai_score = ai_confidence * 10
        scores['ai_confidence'] = {
            'score': round(ai_score, 2),
            'max': 10,
            'value': ai_confidence
        }

        # 计算总分
        total_score = required_score + optional_score + validation_score + ai_score
        final_confidence = min(total_score / 100.0, 1.0)

        # 构建详细分析对象
        breakdown = ConfidenceBreakdown(
            total_score=round(total_score, 2),
            final_confidence=round(final_confidence, 2),
            required_fields_score=round(required_score, 2),
            optional_fields_score=round(optional_score, 2),
            validation_score=round(validation_score, 2),
            ai_confidence_score=round(ai_score, 2),
            scores=scores
        )

        return round(final_confidence, 2), breakdown

    def _validate_phone(self, phone: str) -> bool:
        """
        验证手机号基本格式.

        Args:
            phone: 手机号字符串

        Returns:
            是否为有效手机号
        """
        if not phone:
            return False

        # 去除可能的分隔符
        clean_phone = phone.replace("-", "").replace(" ", "").replace("+86", "")

        # 11位数字
        if len(clean_phone) != 11:
            return False

        # 全是数字
        if not clean_phone.isdigit():
            return False

        return True

    def _validate_phone_strict(self, phone: str) -> bool:
        """
        严格验证手机号（包括号段规则）.

        Args:
            phone: 手机号字符串

        Returns:
            是否符合中国手机号规则
        """
        if not self._validate_phone(phone):
            return False

        clean_phone = phone.replace("-", "").replace(" ", "").replace("+86", "")

        # 必须1开头
        if not clean_phone.startswith("1"):
            return False

        # 第二位必须是3-9（中国手机号段规则）
        if clean_phone[1] not in "3456789":
            return False

        return True

    def _validate_budget_reasonability(
        self, demand_type: DemandType | None, budget_range: str | None
    ) -> bool:
        """
        验证预算合理性.

        Args:
            demand_type: 需求类型
            budget_range: 预算范围

        Returns:
            预算是否合理
        """
        if not budget_range or not demand_type:
            return False

        try:
            # 提取预算数字
            import re
            numbers = re.findall(r'\d+', budget_range)
            if not numbers:
                return False

            min_budget = int(numbers[0])
            max_budget = int(numbers[-1]) if len(numbers) > 1 else min_budget

            # 租房场景：预算应该在 500-50000 元/月
            if demand_type in [DemandType.RENT_WHOLE, DemandType.RENT_SHARED, DemandType.RENT_SHORT]:
                if min_budget < 100 or max_budget > 100000:
                    return False
                if min_budget > 50000:  # 租金超过5万不太合理
                    return False

            # 买房场景：预算应该在 50-10000 万元
            elif demand_type == DemandType.BUY:
                if min_budget < 10 or max_budget > 50000:
                    return False

            # 卖房场景：不验证预算（卖房一般没有预算概念）
            elif demand_type == DemandType.SELL:
                return True

            # 最小值不能大于最大值
            if min_budget > max_budget:
                return False

            return True

        except (ValueError, IndexError):
            return False
